#include "stdafx.h"
#include <iostream>  
#include <algorithm>  
#include "MapGraph.h"  
#include "stdafx.h"
#include "Pict.h"
#include <stdlib.h>
#include <time.h>

Graph::Graph(  )  
{  
	id = nullptr; //new int[0];
	 srand ( time(NULL) );
	xCoord = nullptr; //new int[0];
	yCoord = nullptr; //new int[0];
    nNodes = 0;  
    nEdges = 0;  
    isDirected = true;  
} 
Graph::Graph( const int& nodes, const bool& directed )  
{  
	 srand ( time(NULL) );

	xCoord = new int[nodes];
	yCoord = new int[nodes];
	for(int i = 0; i<nodes;i++)
	{
		xCoord[i] = rand()%210 +20;			//need to replace this with a better method to determine x and y coordinates.
		yCoord[i] = rand()%260 +20;			
	}
    nNodes = nodes;  
    nEdges = 0;  
    isDirected = directed;  
}  
 
Graph::~Graph()  
{
	if (id != nullptr) {
		delete[] id;
	}
	if (xCoord != nullptr) {
		delete[] xCoord;
	}
	if (yCoord != nullptr) {
		delete[] yCoord;
	}
}  
  
clm_it Graph::getEdge( const int& s, const int&t )  
{  
  std::pair<int,int> p( s, t );  
  clm_it mit = link_map.find( p );  
  
  return mit;  
}  
void Graph::createNewGraph(const int& nodes, const bool& directed )  
{  
	old_map = link_map;
	srand ( time(NULL) );
	link_map.clear();
	if (xCoord != nullptr) {
		delete[] xCoord;
	}
	if (yCoord != nullptr) {
		delete[] yCoord;
	}
	 id = new int[nodes];
	xCoord = new int[nodes];
	yCoord = new int[nodes];
	for(int i = 0; i<nodes;i++)
	{
		
tryAgain:xCoord[i] = rand()%330 +20;			//need to replace this with a better method to determine x and y coordinates.
		yCoord[i] = rand()%260 +20;			
		for (int j =0;j< nodes;j++)
		{

			if(i!= j && xCoord[i] <= xCoord[j]+50 && xCoord[i] > xCoord[j]-50 && yCoord[i] <= yCoord[j]+50 && yCoord[i] > yCoord[j]-50)
				goto tryAgain;
		}
	}
    nNodes = nodes;  
    nEdges = 0;  
    isDirected = directed;  
}  
// Check if link exists between end nodes  
bool Graph::edge( const int& s, const int& t)  
{  
  return getEdge( s, t ) != link_map.end();  
}  
  
// Add a link: map node pair with weight  
void Graph::insert( const int& s, const int& t, const double& weight )  
{  
	clm_it mit = link_map.begin();  
	std::map<char,int>::iterator it;
  std::pair <int,int> temp;
    for ( ; mit != link_map.end(); ++ mit )  
    {  
		std::pair<int,int> p = (*mit).first;
		if(p.first == s && p.second != t)
		{
			temp= p;
		}
	}
    link_map.erase(temp);
    std::pair<int,int> p1( s, t );  
    std::pair<int,int> p2( t, s );  
    link_map[ p1 ] = weight;  
	
    if ( !isDirected )  
    {          
        link_map[ p2 ] = weight;  
    }  
  
    nEdges++;  
}  
  void Graph::insert( const int& s, const int& t )  
{  
	clm_it mit = link_map.begin();  
	std::map<char,int>::iterator it;
  std::pair <int,int> temp;
    for ( ; mit != link_map.end(); ++ mit )  
    {  
		std::pair<int,int> p = (*mit).first;
		if(p.first == s)
		{
			temp= p;
		}
	}
    link_map.erase(temp);
    std::pair<int,int> p1( s, t );  

	//std::pair<int,int> p2( t, s );  
    link_map[ p1 ] = 1;  
  
       
        //link_map[ p2 ] = 1;  
    
  
    nEdges++;  
}  
// Remove selected link - remove both directions  
// if graph is not directed  
void Graph::remove( const int& s, const int& t )  
{  
    std::pair<int,int> p1( s, t );  
    std::map< std::pair<int,int>, double>::iterator mit = link_map.find( p1 );  
    link_map.erase( mit );  
  
  
    nEdges--;  
}  
  
// Print the network topology  
void Graph::show() const  
{  
    clm_it mit = link_map.begin();  
  
    for ( ; mit != link_map.end(); ++ mit )  
    {  
      std::pair<int,int> p = (*mit).first;  
      std::cout << p.first  << " " <<  
               p.second << " " <<   
               (*mit).second << std::endl;  
    }  
}  
void Graph::addEdge(int a, int b)
{
	
	int c=-1;
	int d=-1;
	for(int i = 0; i< sizeof(id);i++)
	{
		if(id[i] == a)
			c=a;
		if(id[i] == b)
			d=b;
	}
	if(c!=-1 && d !=-1)
	{
		insert(c,d);
	}
}
void Graph::draw(CPaintDC *dc) const
{
	
	
	
	clm_it mit = link_map.begin();  
	HPEN greenPen=CreatePen(PS_SOLID, 1, RGB(0,255,0));
	dc->SelectObject(greenPen);
    for ( ; mit != link_map.end(); ++ mit )  
    {  
		CPoint point1,point2;
		std::pair<int,int> p = (*mit).first; 
		for(int i = 0; i < sizeof(xCoord);i++)
		{
			if(id[i] == p.first)
			{
				point1.x  = xCoord[i];
				point1.y = yCoord[i];
			}
			if(id[i] == p.second)
			{
				point2.x  = xCoord[i];
				point2.y = yCoord[i];
			}
		}
		
		
		dc->MoveTo(point1);

		dc->LineTo(point2);
		CPen pen;
		
    } 
	HPEN blackPen=CreatePen(PS_SOLID, 1, RGB(0,0,0));
	dc->SelectObject(blackPen);
	CBrush brush2;    // Green 
	dc->SelectObject(&brush2); 
	for(int i=0;i<sizeof(xCoord);i++)
	{
		char intStr[100]; 
		itoa(id[i], intStr,10);
		dc->Ellipse(xCoord[i]-15,yCoord[i]-15,xCoord[i]+15,yCoord[i]+15);
		dc->TextOutA(xCoord[i]-8,yCoord[i]-8,intStr);
		
	}
	
}
   
int Graph::getId(CPoint point)
{
	for(int i=0;i<sizeof(xCoord);i++)
	{
		if(point.x>=xCoord[i]-15 && point.x<=xCoord[i]+15 && point.y>=yCoord[i]-15 && point.y<=yCoord[i]+15)
		{
			return id[i];
		}
	}
	return -1;

}
// Return true if graph is directed; false otherwose  
bool Graph::directed() const  
{  
    return isDirected;  
}  
  
// Return number of network nodes  
int Graph::V() const  
{  
    return nNodes;  
}  
  
// Return number of edges  
int Graph::E() const  
{  
    return nEdges;  
}
void Graph::setIds(std::set<int> ids)
{
	if (id != nullptr) {
		delete[] id;
	}
	id = new int[ids.size()];
	int i =0;
	for(std::set<int>::iterator it =ids.begin(); it != ids.end(); it++)
	{
		id[i++] = *it;
	}
	

	clm_it mit = old_map.begin();  
  
    for ( ; mit != old_map.end(); ++ mit )  
    {  
      std::pair<int,int> p = (*mit).first;  
	  if(ids.find(p.first) != ids.end() && ids.find(p.second) != ids.end())
		  link_map.insert(*mit);  
    }  
	
}